package com.zhiche.lisa.bms.service.receipt.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.zhiche.lisa.bms.dao.mapper.receipt.ReceiptAffirmMapper;
import com.zhiche.lisa.bms.dao.model.invoice.InvoiceReg;
import com.zhiche.lisa.bms.dao.model.receipt.ReceiptAffirm;
import com.zhiche.lisa.bms.dao.model.receipt.ReceiptAffirmDtl;
import com.zhiche.lisa.bms.pojo.vo.receipt.ReceiptAffirmAndDtlVO;
import com.zhiche.lisa.bms.pojo.vo.receipt.ReceiptAffirmDtlAndInvoiceVO;
import com.zhiche.lisa.bms.pojo.vo.receipt.ReceiptAffirmVo;
import com.zhiche.lisa.bms.service.invoice.InvoiceRegService;
import com.zhiche.lisa.bms.service.receipt.ReceiptAffirmDtlService;
import com.zhiche.lisa.bms.service.receipt.ReceiptAffirmService;
import com.zhiche.lisa.core.supports.BaseException;
import com.zhiche.lisa.core.utils.Account.AccountUtil;
import com.zhiche.lisa.core.utils.Account.JwtAccountVO;
import com.zhiche.lisa.core.utils.SnowFlakeId;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;


/**
 * <p>
 * 收款确认 服务实现类
 * </p>
 *
 * @author hongbo
 * @since 2018-09-27
 */
@Service
public class ReceiptAffirmServiceImpl extends ServiceImpl<ReceiptAffirmMapper, ReceiptAffirm> implements ReceiptAffirmService {
    private static final Logger LOGGER = LoggerFactory.getLogger(ReceiptAffirmService.class);
    @Autowired
    private ReceiptAffirmDtlService receiptAffirmDtlService;
    @Autowired
    private SnowFlakeId snowFlakeId;

    @Autowired
    private InvoiceRegService invoiceRegService;

    /**
     * 收款确认分页查询
     *
     * @param page
     * @return
     */
    @Override
    public Page<ReceiptAffirmVo> qureyReceiptAffirmLinePage(Page<ReceiptAffirm> page) {
        try {
            EntityWrapper<ReceiptAffirm> ew = this.buildCondition(page.getCondition());
            List<ReceiptAffirm> list = baseMapper.selectPage(page, ew);
            List<ReceiptAffirmVo> voList = new ArrayList<>();
            for (ReceiptAffirm receiptAffirm : list) {
                ReceiptAffirmVo receiptAffirmVo = this.queryInvoiceFromReceiptAffirmDtl(receiptAffirm);
                voList.add(receiptAffirmVo);
            }
            Page<ReceiptAffirmVo> pageVo = new Page<>();
            BeanUtils.copyProperties(page, pageVo);
            pageVo.setRecords(voList);
            return pageVo;
        } catch (BaseException e) {
            LOGGER.error("ReceiptAffirmServiceImpl.qureyReceiptAffirmLinePage:" + e.getMessage());
            throw new BaseException("获取收款确认失败");
        } catch (Exception e) {
            LOGGER.error("ReceiptAffirmServiceImpl.qureyReceiptAffirmLinePage:" + e.getMessage());
            throw e;
        }
    }

    private ReceiptAffirmVo queryInvoiceFromReceiptAffirmDtl(ReceiptAffirm receiptAffirm) {
        ReceiptAffirmVo receiptAffirmVo = new ReceiptAffirmVo();
        BeanUtils.copyProperties(receiptAffirm, receiptAffirmVo);
        EntityWrapper<ReceiptAffirmDtl> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("head_id", receiptAffirm.getId());
        List<ReceiptAffirmDtl> receiptAffirmDtls = receiptAffirmDtlService.selectList(entityWrapper);
        List<String> invoiceCodeS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(receiptAffirmDtls)) {
            for (ReceiptAffirmDtl receiptAffirmDtl : receiptAffirmDtls) {
                invoiceCodeS.add(receiptAffirmDtl.getInvoiceCode());
            }
        }
        if (!CollectionUtils.isEmpty(invoiceCodeS)) {
            receiptAffirmVo.setInvoiceCodeS(StringUtils.join(invoiceCodeS, ", "));
        }
        return receiptAffirmVo;
    }

    private EntityWrapper<ReceiptAffirm> buildCondition(Map<String, Object> condition) {
        EntityWrapper<ReceiptAffirm> ew = new EntityWrapper<>();
        if (!Objects.equals(condition, null)) {
            for (Map.Entry<String, Object> entry : condition.entrySet()) {
                if (!Objects.isNull(entry.getValue())) {
                    if (!StringUtils.isEmpty(String.valueOf(entry.getValue()))) {
                        if ("billCode".equals(entry.getKey()) && StringUtils.isNoneBlank(entry.getValue().toString())) {
                            ew.like("bill_code", String.valueOf(entry.getValue()));
                        }
                        if ("payName".equals(entry.getKey()) && StringUtils.isNoneBlank(entry.getValue().toString())) {
                            ew.eq("pay_name", String.valueOf(entry.getValue()));
                        }
                        if ("state".equals(entry.getKey()) && StringUtils.isNoneBlank(entry.getValue().toString())) {
                            ew.eq("state", String.valueOf(entry.getValue()));
                        }
                    }
                }
            }
        }
        ew.orderBy("gmt_create desc, id desc");
        return ew;
    }

    /**
     * 收款确认批量删除
     *
     * @param ids
     */
    @Override
    public void deleteReceiptAffirmById(List<Long> ids) {
        try {
            if (CollectionUtils.isEmpty(ids)) throw new BaseException("未获取删除项");
            EntityWrapper<ReceiptAffirmDtl> ew = new EntityWrapper<>();
            ew.in("head_id", ids);
            receiptAffirmDtlService.delete(ew);
            this.deleteBatchIds(ids);
        } catch (BaseException e) {
            LOGGER.error("ReceiptAffirmServiceImpl.deleteReceiptAffirmLineById:" + e.getMessage());
            throw new BaseException("收款确认删除失败");
        } catch (Exception e) {
            LOGGER.error("ReceiptAffirmServiceImpl.deleteReceiptAffirmLineById:" + e.getMessage());
            throw e;
        }
    }

    /**
     * 新增收款确认
     *
     * @param receiptAffirm
     * @param receiptAffirmDtls
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void insertReceiptAffirm(ReceiptAffirm receiptAffirm, List<ReceiptAffirmDtl> receiptAffirmDtls, boolean checkDiffSum) {
        try {
            if (Objects.isNull(receiptAffirm)) throw new BaseException("未获取收款确认主表");
            if (CollectionUtils.isEmpty(receiptAffirmDtls)) throw new BaseException("未获取收款确认明细");
            if (StringUtils.isEmpty(receiptAffirm.getPayName())) throw new BaseException("未获取付款方");
            if (checkDiffSum) {
                this.checkDiffSumAndSum(receiptAffirm, receiptAffirmDtls);
            }
            if (receiptAffirm.getTenantId() == null) {
                JwtAccountVO jwtAccountVO = AccountUtil.getAccountInfoFromSecurityContext();
                if (Objects.nonNull(jwtAccountVO)) {
                    receiptAffirm.setCreator(new Long(jwtAccountVO.getAccountId()));
                    receiptAffirm.setTenantId(Long.valueOf(jwtAccountVO.getTenantId()));
                }
            }
            receiptAffirm.setBillCode(("RP" + snowFlakeId.nextId()));
            receiptAffirm.setGmtCreate(new Date());
            if (receiptAffirm.getState() == null) {
                receiptAffirm.setState(0);
            }
            List<ReceiptAffirmDtl> list = new ArrayList<>();
            Integer integer = updateInvoiceSum(receiptAffirmDtls);
            if (integer != null) {
                receiptAffirm.setState(integer);
            }
            if(receiptAffirm.getReceiptSum()==null){
                receiptAffirm.setReceiptSum(BigDecimal.ZERO);
            }
            if(receiptAffirm.getSum()==null){
                receiptAffirm.setSum(BigDecimal.ZERO);
            }
            receiptAffirm.setReceiptSum(receiptAffirm.getReceiptSum().add(receiptAffirm.getSum()));
            this.insert(receiptAffirm);
            Long a = receiptAffirm.getId();
            for (ReceiptAffirmDtl receiptAffirmDtl : receiptAffirmDtls) {
                receiptAffirmDtl.setHeadId(a);
                // 计算金额
                if (receiptAffirmDtl.getAccountSum() != null && receiptAffirmDtl.getInvoiceSum() != null) {
                    receiptAffirmDtl.setUndeteSum(receiptAffirmDtl.getInvoiceSum().subtract(receiptAffirmDtl.getAccountSum()).setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                // 格式化金额
                if (receiptAffirmDtl.getAccountSum() != null) {
                    receiptAffirmDtl.setAccountSum(receiptAffirmDtl.getAccountSum().setScale(2, BigDecimal.ROUND_HALF_UP));
                }else{
                    receiptAffirmDtl.setAccountSum(BigDecimal.ZERO);
                }
                if (receiptAffirmDtl.getInvoiceSum() != null) {
                    receiptAffirmDtl.setInvoiceSum(receiptAffirmDtl.getInvoiceSum().setScale(2, BigDecimal.ROUND_HALF_UP));
                }else{
                    receiptAffirmDtl.setInvoiceSum(BigDecimal.ZERO);
                }
                if (receiptAffirmDtl.getReceiptSum() != null) {
                    receiptAffirmDtl.setReceiptSum(receiptAffirmDtl.getReceiptSum().setScale(2, BigDecimal.ROUND_HALF_UP));
                }else{
                    receiptAffirmDtl.setReceiptSum(BigDecimal.ZERO);
                }
                receiptAffirmDtl.setReceiptSum(receiptAffirmDtl.getReceiptSum().add(receiptAffirmDtl.getAccountSum()));
                list.add(receiptAffirmDtl);
            }
            receiptAffirmDtlService.insertBatch(list);
        } catch (BaseException e) {
            LOGGER.error("ReceiptAffirmServiceImpl.insertReceiptAffirm:" + e.getMessage());
            throw e;
        } catch (Exception e) {
            LOGGER.error("ReceiptAffirmServiceImpl.insertReceiptAffirm:" + e.getMessage());
            throw e;
        }
    }

    /**
     * 根据id号查找对应的收款确认信息
     *
     * @param receiptAffirmId
     * @return
     */
    @Override
    public ReceiptAffirmAndDtlVO selectReceiptAndDtlById(Long receiptAffirmId) {
        ReceiptAffirmAndDtlVO receiptAffirmAndDtlVO = new ReceiptAffirmAndDtlVO();
        ReceiptAffirm receiptAffirm = this.selectById(receiptAffirmId);
        if (receiptAffirm != null) {
            receiptAffirmAndDtlVO.setReceiptAffirm(receiptAffirm);
            List<ReceiptAffirmDtl> receiptAffirmDtls = receiptAffirmDtlService.selectReceiptAffirmDtlByHeadId(receiptAffirmId);
            List<ReceiptAffirmDtlAndInvoiceVO> receiptAffirmDtlAndInvoiceVOS = receiptAffirmDtlService.bindInvoiceReceiptAffirm(receiptAffirmDtls);
            receiptAffirmAndDtlVO.setReceiptAffirmDtlAndInvoiceVOS(receiptAffirmDtlAndInvoiceVOS);
        }
        return receiptAffirmAndDtlVO;
    }

    /**
     * 修改指定收款确认信息
     *
     * @param receiptAffirm
     * @param receiptAffirmDtls
     */
    @Override
    public void updateReceiptAffirmAndDtl(ReceiptAffirm receiptAffirm, List<ReceiptAffirmDtl> receiptAffirmDtls) {
        try {
            if (Objects.isNull(receiptAffirm)) throw new BaseException("未获取收款确认主表");
            if (CollectionUtils.isEmpty(receiptAffirmDtls)) throw new BaseException("未获取收款确认明细");
            if (StringUtils.isEmpty(receiptAffirm.getPayName())) throw new BaseException("未获取付款方");
            ReceiptAffirm oldReceiptAffirm = this.selectById(receiptAffirm.getId());
            if (Objects.isNull(oldReceiptAffirm)) throw new BaseException("指定收款确认主表不存在");
            this.checkDiffSumAndSum(receiptAffirm, receiptAffirmDtls);
            Integer integer = updateInvoiceSum(receiptAffirmDtls);
            if (integer != null) {
                receiptAffirm.setState(integer);
            }
            receiptAffirm.setReceiptSum(oldReceiptAffirm.getReceiptSum().add(receiptAffirm.getSum()));
            this.updateById(receiptAffirm);
            receiptAffirmDtlService.selectReceiptAffirmDtlByHeadId(receiptAffirm.getId());
            for (ReceiptAffirmDtl receiptAffirmDtl : receiptAffirmDtls) {
                ReceiptAffirmDtl oldReceiptAffirmDtl = receiptAffirmDtlService.selectById(receiptAffirmDtl.getId());

                // 计算金额
                if (receiptAffirmDtl.getAccountSum() != null && receiptAffirmDtl.getInvoiceSum() != null) {
                    receiptAffirmDtl.setUndeteSum(receiptAffirmDtl.getInvoiceSum().subtract(receiptAffirmDtl.getAccountSum()).setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                // 格式化金额
                if (receiptAffirmDtl.getAccountSum() != null) {
                    receiptAffirmDtl.setAccountSum(receiptAffirmDtl.getAccountSum().setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                if (receiptAffirmDtl.getInvoiceSum() != null) {
                    receiptAffirmDtl.setInvoiceSum(receiptAffirmDtl.getInvoiceSum().setScale(2, BigDecimal.ROUND_HALF_UP));
                }
                receiptAffirmDtl.setReceiptSum(oldReceiptAffirmDtl.getReceiptSum().add(receiptAffirmDtl.getAccountSum()));
            }
            receiptAffirmDtlService.updateBatchById(receiptAffirmDtls);
        } catch (BaseException e) {
            LOGGER.error("ReceiptAffirmServiceImpl.updateReceiptAffirm:" + e.getMessage());
            throw e;
        } catch (Exception e) {
            LOGGER.error("ReceiptAffirmServiceImpl.updateReceiptAffirm:" + e.getMessage());
            throw e;
        }
    }

    /**
     * 更新发票登记金额
     *
     * @param receiptAffirmDtls
     * @return 状态
     */
    private Integer updateInvoiceSum(List<ReceiptAffirmDtl> receiptAffirmDtls) {
        BigDecimal sumInvoiceReSum = new BigDecimal("0");
        BigDecimal sumInvoiceSum = new BigDecimal("0");

        if (!CollectionUtils.isEmpty(receiptAffirmDtls)) {
            List<InvoiceReg> invoiceRegList = Lists.newArrayList();

            for (ReceiptAffirmDtl raf : receiptAffirmDtls) {
                InvoiceReg reg = invoiceRegService.selectById(raf.getInvoiceId());
                reg.setInvoiceReSum((reg.getInvoiceReSum() == null ? BigDecimal.ZERO : reg.getInvoiceReSum())
                        .add(
                                raf.getAccountSum() == null ? BigDecimal.ZERO : raf.getAccountSum()
                        ));

                reg.setInvoiceLackSum((reg.getInvoiceLackSum() == null ? BigDecimal.ZERO : reg.getInvoiceLackSum())
                        .subtract(
                                raf.getAccountSum() == null ? BigDecimal.ZERO : raf.getAccountSum()
                        ));

                reg.setInvoiceSum(raf.getInvoiceSum());
                if (reg.getInvoiceReSum().add(reg.getInvoiceLackSum()).compareTo(reg.getInvoiceSum()) != 0)
                    throw new BaseException("关联发票金额异常");

                sumInvoiceReSum = sumInvoiceReSum.add(reg.getInvoiceReSum());
                sumInvoiceSum = sumInvoiceSum.add(reg.getInvoiceSum());

                invoiceRegList.add(reg);
            }
            invoiceRegService.updateInvoiceReSum(invoiceRegList);
        }
        int i = sumInvoiceReSum.compareTo(sumInvoiceSum);
        if (sumInvoiceReSum.compareTo(BigDecimal.ZERO) == 0) {
            return 0;
        } else if (i == 0) {
            return 2;
        } else if (i <= 0) {
            return 1;
        } else {
            return null;
        }
    }


    /**
     * 到账总金额及差异金额校验
     *
     * @param receiptAffirm
     * @param receiptAffirmDtls
     */
    private void checkDiffSumAndSum(ReceiptAffirm receiptAffirm, List<ReceiptAffirmDtl> receiptAffirmDtls) {
        //到账总金额
        BigDecimal sum = new BigDecimal("0");
        //差异金额
        //BigDecimal diff = new BigDecimal("0");
        for (ReceiptAffirmDtl receiptAffirmDtl : receiptAffirmDtls) {
            if (receiptAffirmDtl.getReceiptSum() == null) {
                receiptAffirmDtl.setReceiptSum(BigDecimal.ZERO);
            }
            if (receiptAffirmDtl.getAccountSum() == null) {
                receiptAffirmDtl.setAccountSum(BigDecimal.ZERO);
            } else {
                sum = sum.add(receiptAffirmDtl.getAccountSum());
            }
            //diff.add((receiptAffirmDtl.getInvoiceSum().subtract(receiptAffirmDtl.getUndeteSum().add(receiptAffirmDtl.getAccountSum()))));
        }
        //到账总金额比较
        //int i = sum.compareTo(receiptAffirm.getSum());
        //if (!(i == 0)) {
        if (receiptAffirm.getReceiptSum() == null) {
            receiptAffirm.setReceiptSum(BigDecimal.ZERO);
        }
        if (sum.compareTo(receiptAffirm.getSum()) != 0) {
            throw new BaseException("到账总金额输入有误");
        }
        //差异总金额比较
        //int j = diff.compareTo(receiptAffirm.getDiffSum());
        //if (j == 0) {
        //    //判断是否有差异金额
        //    int k = diff.compareTo(new BigDecimal("0"));
        //    if (!(k == 0)) {
        //        if (StringUtils.isEmpty(receiptAffirm.getDiffCause())) {
        //            throw new BaseException("请输入差异原因");
        //        }
        //    }
        //} else {
        //    throw new BaseException("差异总金额输入有误");
        //}
    }
}
